use super::Authenticator;
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use std::net::SocketAddr;

pub struct HttpAuthenticator {
    url: String,
    client: reqwest::Client,
}

impl HttpAuthenticator {
    pub fn new(url: String, insecure: bool) -> anyhow::Result<Self> {
        let client = reqwest::Client::builder()
            .danger_accept_invalid_certs(insecure)
            .timeout(std::time::Duration::from_secs(10))
            .build()?;

        Ok(Self { url, client })
    }
}

#[derive(Serialize)]
struct AuthHttpRequest {
    addr: String,
    auth: String,
    tx: u64,
}

#[derive(Deserialize)]
struct AuthHttpResponse {
    ok: bool,
    id: String,
}

#[async_trait]
impl Authenticator for HttpAuthenticator {
    async fn authenticate(
        &self,
        addr: SocketAddr,
        auth: &str,
        tx: u64,
    ) -> anyhow::Result<(bool, String)> {
        let req = AuthHttpRequest {
            addr: addr.to_string(),
            auth: auth.to_string(),
            tx,
        };

        let resp = self
            .client
            .post(&self.url)
            .json(&req)
            .send()
            .await?
            .json::<AuthHttpResponse>()
            .await?;

        Ok((resp.ok, resp.id))
    }
}
